package com.server;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

import com.interf.IRemoteRequester;
import com.interf.Requester;
import com.interf.SyncTimeData;
import com.thread.CallableRequester;

public class RemoteRequester extends UnicastRemoteObject implements
		IRemoteRequester {

	private static final long serialVersionUID = 1L;

	protected RemoteRequester() throws RemoteException {
		super();
	}

	
	@Override
	public <T> ArrayList<T> makeRequest(Requester<T> r, int numberThread, long offsetTime, long timetoTest) throws RemoteException {
		ArrayList<T> result = new ArrayList<T>();
		
		System.out.println("Get request from: " + r.getHostName());
		System.out.println("Number of threads to executed: " + numberThread);
		//wait for synchronization

		while (System.currentTimeMillis() + offsetTime < timetoTest)
			try {
				Thread.sleep(100);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
		
		System.out.println("Begin testing ...");
		//Make request by Executor
		ExecutorService eservice = Executors.newFixedThreadPool(numberThread);
	      
	      ArrayList<FutureTask<T>> arrFutureTask = new ArrayList<FutureTask<T>>();
	      for (int i = 0; i < numberThread; i++)
	      {
	    	  arrFutureTask.add((FutureTask<T>) eservice.submit(new CallableRequester(r)));
	      }
	      
	      eservice.shutdown();
	      try {
	    	  	eservice.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
	  			for (FutureTask<T> futureTask : arrFutureTask) {
					result.add(futureTask.get());
				}
	  			return result;
	      } catch (Exception e) {
	    	  e.printStackTrace();
	      }
	      
		
		return null;

	}


	@Override
	public SyncTimeData getSyncData() {
		long timeofArrival = System.currentTimeMillis();
		// Lag time when creating object??
		SyncTimeData result = new SyncTimeData();
		result.requestToA = timeofArrival;
		result.responseToL = System.currentTimeMillis();
		System.out.println(result.responseToL);
		return result;
	}

}
